package com.wing.cabinet.controller.websocket;

import com.alibaba.fastjson.JSONObject;
import com.wing.cabinet.controller.websocket.service.BaseConnectService;
import com.wing.cabinet.service.CommandLogService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Component
@ServerEndpoint("/websocket/cabOpen")
public class CabinetOpenServer {

    private final static String  msgPrefix = "cabCodes:";

    private final static String  commandMsgPrefix = "commandData:";

    private final static Logger log = LoggerFactory.getLogger(CabinetOpenServer.class);
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    //柜子面板
    private static Map<String,Session> webSocketMap = new HashMap<>();
    //小程序
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static Map<String,Session> appletsSocketMap = new HashMap<>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    private static Session currentSession;

    private static CommandLogService commandLogService;

    private static ApplicationContext applicationContext;


    public static void setApplicationContext(ApplicationContext applicationContext) {
        CabinetOpenServer.applicationContext = applicationContext;
    }

    //接收userId
    //private String userId="";
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session) {
        log.info("sessionId = "+ session.getId());
        log.info("sessionQuery = "+session.getQueryString());
//        log.info(session.get);
        this.session = session;
        currentSession=session;
        //webSocketSet.add(session);     //加入set中
        //this.userId=userId;
        if (commandLogService==null){
            commandLogService=applicationContext.getBean(CommandLogService.class);
        }

    }



    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        log.info("close");
        /*for (Map.Entry<String,Session> entry : webSocketMap.entrySet()) {
            if(session.equals(entry.getValue())){
                webSocketMap.remove(entry.getKey());  //从map中删除
            }
        }*/

        Iterator<Map.Entry<String, Session>> iterator = webSocketMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Session> item = iterator.next();
            if(session.equals(item.getValue())){
                // 在迭代过程中删除元素
                iterator.remove();
            }
        }

        Iterator<Map.Entry<String, Session>> appletsIterator = appletsSocketMap.entrySet().iterator();
        while (appletsIterator.hasNext()) {
            Map.Entry<String, Session> item = appletsIterator.next();
            if(session.equals(item.getValue())){
                // 在迭代过程中删除元素
                iterator.remove();
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * 1、连接消息：connect  2、心跳 ：heartbeat 3、发送指令：codeSend  4、接收指令：codeReceive  5、打印消息：print  6、app异常消息：appException  6、远程开柜的反馈：remoteOpenCab
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自窗口的信息:"+message);
        currentSession=session;
        try {
//            boolean bool=true;
//            if(StringUtils.isNotBlank(message)){
//                int i = message.indexOf(msgPrefix);
//                if(i!=-1){
//                    bool=false;
//                    String replace = message.replace(msgPrefix, "");
//                    String[] split = replace.split(",");
//                    String enterpriseCode="";
//                    if (split.length>0){
//                        enterpriseCode=split[split.length-1];
//                    }
//                    for(int j=0;j<split.length-1;j++){
//                        log.info("创建session。。。 柜子编号为"+split[j]);
//                        webSocketMap.put(enterpriseCode+"-"+split[j],session);
//                        log.info("柜子编号:"+enterpriseCode+"-"+split[j]+";session:"+session.getId());
//                    }
//                }
//                try{
//                    int j=message.indexOf(commandMsgPrefix);
//                    if (j!=-1){
//                        bool=false;
//                        String command = message.replace(commandMsgPrefix, "");
//                        CommandLog commandLog=JSONObject.parseObject(command, CommandLog.class);
////                        if(CommandLog.Type.reconnect.equals(commandLog.getType())){
////                            String enterpriseCode=commandLog.getEnterpriseCode();
////                            webSocketMap.put(enterpriseCode+"-"+commandLog.getCabCode(),session);
////                        }
//                        commandLogService.save(commandLog);
//                    }
//                }catch (Exception e){
//                    log.error("json parse msg fail",e);
//                }
//
//            }
//            if (bool){
//                session.getBasicRemote().sendText(message);
//            }

            if(StringUtils.isNotBlank(message)){
                JSONObject jsonObject = JSONObject.parseObject(message);
                String type = jsonObject.getString("type"); //消息类型 heartbeat
                String enterpriseCode = jsonObject.getString("enterpriseCode");  // 企业编号
                String cabCode = jsonObject.getString("cabCode"); //柜子编号
                String client = jsonObject.getString("client"); //登陆客户端 client: cab、mobile、applets
                if("mobile".equals(client)){
                    log.error("手机APP发送过来的消息,丢掉");
                    return;
                }
                if("applets".equals(client)){
                    String phone = jsonObject.getString("phone"); //手机号
                    appletsSocketMap.put(enterpriseCode + "-" + cabCode + "-" + phone,session);
                }else{
                    webSocketMap.put(enterpriseCode + "-" + cabCode,session);
                }
                //String body = jsonObject.getString("body");
                //log.info("创建session。。。 柜子编号为"+ cabCode);
                //log.info("柜子编号:"+enterpriseCode + "-" + cabCode +";session:"+session.getId());
//                CountDownLatch c = new CountDownLatch(1);
//                c.await(5000, TimeUnit.MICROSECONDS);

                BaseConnectService baseConnectService = (BaseConnectService)Class.forName("com.wing.cabinet.controller.websocket.service.impl."+ServiceType.typeMap.get(type)).newInstance();
                baseConnectService.logicMessage(message);

            }

        } catch (Exception e) {
            log.error("receive msg fail",e);
        }

    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误",error);
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送(发给柜子面板)
     */
    public static void sendMessage(String enterpriseCode,String cabCode,String message) throws IOException {
        //Map map=new HashMap();
        //map.put("cabCode",cabCode);
        //map.put("spaceCode",spaceCode);
        //log.info("enterpriseCode:{},cabCode:{},spaceCode:{}",enterpriseCode,cabCode,spaceCode);
        //Session session = webSocketMap.get(enterpriseCode+"-"+cabCode);
        //
        //log.info("开柜session = "+session);
        //if (session!=null){
        //    try{
        //        session.getBasicRemote().sendText(JSONObject.toJSONString(map));
        //    }catch (Exception e){
        //        log.error("send msg fail",e);
        //        currentSession.getBasicRemote().sendText(JSONObject.toJSONString(map));
        //    }
        //
        //}
        log.info("发送:enterpriseCode:{},cabCode:{},spaceCode:{}",enterpriseCode,cabCode,message);
        Session session = webSocketMap.get(enterpriseCode+"-"+cabCode);

        //log.info("开柜session = "+session);
        if (session!=null){
            try{
                session.getBasicRemote().sendText(message);
            }catch (Exception e){
                log.error("send msg fail",e);
                currentSession.getBasicRemote().sendText(message);
            }

        }
    }

    /**
     * 实现服务器主动推送(发给小程序)
     */
    public static void sendAppletMessage(String enterpriseCode,String cabCode,String phone, String message) throws IOException {
        log.info("发送小程序消息:enterpriseCode:{},cabCode:{},phone:{},message:{}",enterpriseCode,cabCode,phone,message);
        Session session = appletsSocketMap.get(enterpriseCode+"-"+cabCode+"-"+phone);

        //log.info("开柜session = "+session);
        if (session!=null){
            try{
                session.getBasicRemote().sendText(message);
            }catch (Exception e){
                log.error("send msg fail",e);
                currentSession.getBasicRemote().sendText(message);
            }

        }
    }

    /**
     * 群发自定义消息
     * */
    public static void sendInfo(String message){
        log.info("推送消息到窗口，推送内容:"+message);
        for (Map.Entry<String,Session> entry : webSocketMap.entrySet()) {
            try {
                //这里可以设定只推送给这个userId的，为null则全部推送
                entry.getValue().getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("send msg error",e);
                e.printStackTrace();
                continue;
            }
        }
    }


}
